library(data.table)
library(ggplot2)
library(beanplot) # for beanplots
library(gridExtra) # to combine ggplots together
library(grid) # to combine ggplots together
knitr::opts_knit$set(root.dir = rprojroot::find_rstudio_root_file()) # tell RStudio to use project root directory as the root for this notebook. Needed since we are storing code in a separate directory.
Load data
# BioTime
load('data/biotime_blowes/bt_malin.Rdata')
bt <- data.table(bt_malin); rm(bt_malin)
# Temperature average, trends, and seasonality
temperature <- fread('output/temperature_byrarefyID.csv.gz')
# microclimates
microclim <- fread('output/microclimates.csv.gz', drop = 1)
# NPP
npp <- fread('output/npplandocean.csv.gz')
# Body size
bs <- fread('output/mass_byrarefyid.csv.gz', drop = 1)
bs[, ':='(STUDY_ID = NULL, REALM = NULL, taxa_mod = NULL)] # remove unnecessary columns
# Mobility
speed <- fread('output/speed_byrarefyID.csv.gz', drop = 1)
speed[, ':='(STUDY_ID = NULL, REALM = NULL, taxa_mod = NULL)] # remove unnecessary columns
# Lifespan
lsp <- fread('output/lifespan_byrarefyID.csv.gz')
# CTI
cti <- fread('output/cti_byrarefyID.csv.gz')
# consumer vs. producer
consfrac <- fread('output/consfrac_byrarefyID.csv.gz')
# richness
rich <- fread('output/richness_by_rarefyID.csv.gz') # number of species
# endotherm vs. ectotherm
endofrac <- fread('output/endofrac_byrarefyID.csv.gz') # endotherm vs. ectotherm classifications
# human impact
human <- fread('output/humanimpact_by_rarefyID.csv.gz')
# %veg
veg <- as.data.table(readRDS('output/vct_by_rarefyID.rds'))
veg[, veg := (`tree cover % (mean)` + 0.5 * `non-tree veg. % (mean)`)/100] # veg index from 0 (all non-veg) to 1 (all tree). Non-tree veg counts as 0.5.
Plot a turnover example
First is a long time-series, next one shows an example result of removing the first year of self-comparison.
#bt[, .(n = .N), by = rarefyID][n > 50,]
ggplot(bt[rarefyID == '339_1085477'], aes(YEAR, Jtu_base)) +
geom_point() +
geom_smooth(method = 'lm') +
xlab('Year') + ylab('Jaccard dissimilarity')

ggplot(bt[rarefyID == '489_16754'], aes(YEAR, Jtu_base)) +
geom_point() +
geom_smooth(method = 'lm', se = FALSE) +
xlab('Year') + ylab('Jaccard dissimilarity') +
geom_smooth(data = bt[rarefyID == '489_16754' & YEAR != 2000], method = 'lm', se = FALSE, color = 'red')

Assemble dataset of beta diversity trends (temporal turnover) and covariates
# calculate temporal turnover
calctrend <- function(y, YEAR, nm = 'y'){ # function to calc trends
# turn off warnings for the following
defaultW <- getOption("warn")
options(warn = -1)
mod <- lm(y ~ YEAR)
out <- list(y = coef(mod)[2], # coef for the slope
y_se = sqrt(diag(vcov(mod)))[2]) # SE
names(out) <- c(nm, paste0(nm, '_se'))
options(warn = defaultW)
return(out)
}
# function to calc trends, removing first year with 0
calctrendrem0 <- function(y, YEAR, nm = 'y'){
# turn off warnings for the following
defaultW <- getOption("warn")
options(warn = -1)
if(length(YEAR)>2){
o <- order(YEAR)
YEAR2 <- YEAR[o][2:length(YEAR)]
y2 <- y[o][2:length(y)]
if(sum(!is.na(y2)) >= 2){ # make sure enough values to fit a line
mod <- lm(y2 ~ YEAR2)
out <- list(y = coef(mod)[2], # coef for the slope
y_se = sqrt(diag(vcov(mod)))[2]) # SE
names(out) <- c(nm, paste0(nm, '_se'))
options(warn = defaultW)
return(out)
} else {
out <- list(y = NA_real_, y_se = NA_real_)
names(out) <- c(nm, paste0(nm, '_se'))
options(warn = defaultW)
return(out)
}
} else {
out <- list(y = NA_real_, y_se = NA_real_)
names(out) <- c(nm, paste0(nm, '_se'))
options(warn = defaultW)
return(out)
}
}
calcfirstlast <- function(y, YEAR, nm = 'y'){ # function to get distance from last to first year
# turn off warnings for the following
defaultW <- getOption("warn")
options(warn = -1)
if(length(YEAR)>1){
o <- order(YEAR)
YEAR2 <- YEAR[o][2:length(YEAR)]
y2 <- y[o][2:length(y)]
out <- list(y = y2[length(y2)], # dissimilarity for last year
y_se = NA_real_)
} else {
out <- list(y = NA_real_, y_se = NA_real_)
}
names(out) <- c(nm, paste0(nm, '_se'))
options(warn = defaultW)
return(out)
}
setkey(bt, STUDY_ID, rarefyID, YEAR)
if(file.exists('temp/trendstemp.rds')){
trends <- readRDS('temp/trendstemp.rds')
} else {
trends1 <- bt[, calctrend(Jtu_base, YEAR, 'Jtutrend'),
by = .(REALM, Biome, taxa_mod, STUDY_ID, rarefyID, rarefyID_x, rarefyID_y)] # calculate trend in Jaccard turnover from first year, plus SEs
trends2 <- bt[, calctrend(Jbeta_base, YEAR, 'Jbetatrend'),
by = .(rarefyID)] # calculate trend in total Jaccard' beta diversity's from first year,
trends3 <- bt[, calctrend(1-Horn_base, YEAR, 'Horntrend'),
by = .(rarefyID)] # calculate trend in Horn-Morisita from first year. Convert to dissimilarity.
trends4 <- bt[, .(Strend = coef(lm(I(log(S)) ~ YEAR))[2]), by = .(rarefyID)] # trend in log(S)
trends5 <- bt[, calctrendrem0(Jtu_base, YEAR, 'Jtutrendrem0'),
by = .(rarefyID)] # calculate trend in Jaccard turnover without first year
trends6 <- bt[, calctrendrem0(Jbeta_base, YEAR, 'Jbetatrendrem0'),
by = .(rarefyID)]
trends7 <- bt[, calctrendrem0(1-Horn_base, YEAR, 'Horntrendrem0'),
by = .(rarefyID)]
trends8 <- bt[, calcfirstlast(Jtu_base, YEAR, 'Jtulast'),
by = .(rarefyID)]
trends9 <- bt[, calcfirstlast(Jbeta_base, YEAR, 'Jbetalast'),
by = .(rarefyID)]
trends10 <- bt[, calcfirstlast(1-Horn_base, YEAR, 'Hornlast'),
by = .(rarefyID)]
nyrBT <- bt[, .(nyrBT = length(YEAR),
minyrBT = min(YEAR),
maxyrBT = max(YEAR),
medianyrBT = median(YEAR),
meanyrBT = mean(YEAR)),
by = .(rarefyID)] # number of years in time-series
trends <- merge(trends1, trends2) # merge in total J and Horn-Morisita
trends <- merge(trends, trends3)
trends <- merge(trends, trends5)
trends <- merge(trends, trends6)
trends <- merge(trends, trends7)
trends <- merge(trends, trends8)
trends <- merge(trends, trends9)
trends <- merge(trends, trends10)
trends <- merge(trends, nyrBT)
saveRDS(trends, file = 'temp/trendstemp.rds')
}
Add covariates
# add covariates
trends <- merge(trends, temperature[, .(rarefyID, tempave, tempave_metab, temptrend, seas)], all.x = TRUE, by = 'rarefyID') # temperature ave, ave metabolic, trend, and seasonality
trends <- merge(trends, microclim[, .(rarefyID, microclim = Temp_sd20km)], all.x = TRUE, by = 'rarefyID') # microclimates
trends <- merge(trends, npp, all.x = TRUE, by = 'rarefyID') # npp
trends <- merge(trends, bs[, .(rarefyID, mass_mean_weight, mass_sd_weight)], all.x = TRUE) # body size mass (g)
trends <- merge(trends, speed[, .(rarefyID, speed_mean_weight, speed_sd_weight)], all.x = TRUE) # speed (km/hr)
trends <- merge(trends, lsp[, .(rarefyID, lifespan_mean_weight, lifespan_sd_weight)], all.x = TRUE) # lifespan (yr)
trends <- merge(trends, cti[, .(rarefyID, thermal_bias)], all.x = TRUE) # thermal bias (degC)
trends <- merge(trends, consfrac[, .(rarefyID, consfrac)], all.x = TRUE) # fraction consumers
trends <- merge(trends, rich, all.x = TRUE) # species richness
trends <- merge(trends, endofrac[, .(rarefyID, endofrac)], all.x = TRUE) # endotherm vs. ectotherm
trends <- merge(trends, human[, .(rarefyID, human_bowler = atc, human_venter = hfp, human_halpern = himp)], all.x = TRUE) # human impact
trends <- merge(trends, veg[, .(rarefyID, veg = veg)], all.x = TRUE) # vegetation index
trends[REALM == 'Marine', veg := 0] # veg index is 0 at sea
Do some basic checks of the turnover calculations
Histograms of temporal change
# basic checks
trends
x <- trends[, hist(Jtutrend)]

x <- trends[, hist(Jbetatrend)]

x <- trends[, hist(Horntrend)]

x <- trends[, hist(Jtutrendrem0)]

x <- trends[, hist(Jbetatrendrem0)]

x <- trends[, hist(Horntrendrem0)]

x <- trends[, hist(Jtulast)]

x <- trends[, hist(Jbetalast)]

x <- trends[, hist(Hornlast)]

Change compared to number of years in time-series
# number of year
trends[, summary(nyrBT)]
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.000 2.000 4.000 5.519 7.000 97.000
x <- trends[, hist(nyrBT)]

trends[, plot(nyrBT, Jtutrend, log = 'x', col = '#00000033')]
NULL

trends[, plot(nyrBT, Jtutrendrem0, log = 'x', col = '#00000033')]
NULL

trends[, plot(nyrBT, Jtulast, log = 'x', col = '#00000033')]
NULL

Change compared to number of species in time-series
# number of species
trends[, summary(Nspp)]
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.00 6.00 11.00 19.35 24.00 1427.00
x <- trends[, hist(Nspp)]

trends[, plot(Nspp, Jtutrend, log = 'x', col = '#00000033')]
NULL

trends[, plot(Nspp, Jtutrendrem0, log = 'x', col = '#00000033')]
NULL

trends[, plot(Nspp, Jtulast, log = 'x', col = '#00000033')]
NULL

Remove studies with only 1 species
nrow(trends)
trends <- trends[Nspp > 1, ]
nrow(trends)
Turnover calculations are correlated, though less so for Horn
# are turnover calculations correlated?
ggplot(trends, aes(Jbetatrendrem0, Jtutrendrem0)) +
geom_point(alpha = 0.3) +
geom_smooth()
ggplot(trends, aes(Jbetatrendrem0, Horntrendrem0)) +
geom_point(alpha = 0.3) +
geom_smooth()
Temporal turnover is not all that correlated between including first year or not.
ggplot(trends, aes(Jtutrend, Jtutrendrem0)) +
geom_point(alpha = 0.3) +
geom_smooth() +
geom_abline(a = 0, b = 1)
ggplot(trends, aes(Jbetatrend, Jbetatrendrem0)) +
geom_point(alpha = 0.3) +
geom_smooth() +
geom_abline(a = 0, b = 1)
ggplot(trends, aes(Horntrend, Horntrendrem0)) +
geom_point(alpha = 0.3) +
geom_smooth() +
geom_abline(a = 0, b = 1)
Compare covariates across realms
i <- trends[, !duplicated(rarefyID)]; sum(i)
par(mfrow=c(5,3))
beanplot(rarefyID_y ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Latitude (degN)', ll = 0.05)
beanplot(tempave ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Temperature (degC)', ll = 0.05)
beanplot(tempave_metab ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Metabolic Temperature (degC)', ll = 0.05, bw = 'nrd0') # nrd0 bandwidth to calculation gap
beanplot(seas ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Seasonality (degC)', ll = 0.05)
beanplot(microclim ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Microclimates (degC)', ll = 0.05)
beanplot(temptrend ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Temperature trend (degC/yr)', ll = 0.05)
beanplot(mass_mean_weight ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Mass (g)', ll = 0.05, log = 'y')
beanplot(speed_mean_weight +1 ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Speed (km/hr)', ll = 0.05, log = 'y')
beanplot(lifespan_mean_weight ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Lifespan (yr)', ll = 0.05, log = 'y')
#beanplot(consfrac ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Consumers (fraction)', ll = 0.05, log = '') # too sparse
#beanplot(endofrac ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Endotherms (fraction)', ll = 0.05, log = '') # too sparse
beanplot(Nspp ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Number of species', ll = 0.05, log = 'y')
beanplot(thermal_bias ~ REALM, data = trends[i & !is.na(thermal_bias),], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Thermal bias (degC)', ll = 0.05)
beanplot(npp ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'NPP', ll = 0.05)
beanplot(veg ~ REALM, data = trends[i & REALM !='Marine',], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'NPP', ll = 0.05)
Marine are in generally warmer locations (seawater doesn’t freeze) Marine have much lower seasonality. Marine and freshwater have some very small masses (plankton), but much of dataset is similar to terrestrial. Marine has a lot of slow, crawling organisms, but land has plants. Land also has birds (fast).
Plot turnover vs. temperature
Time-series length and temperature trend?
ggplot(trends, aes(temptrend, nyrBT)) +
geom_point() +
geom_smooth() +
scale_y_log10()
Plot turnover vs. explanatory variables
Lines are ggplot smoother fits.
Strong trends with temperature change, but trends are pretty symmetric around no trend in temperature, which implies warming or cooling drives similar degree of community turnover. Some indication of less turnover for larger organisms (mass) Higher turnover on land with higher seasonality? More turnover for shorter-lived organisms? No really clear differences among realms.
Write out
write.csv(trends, gzfile('output/turnover_w_covariates.csv.gz'), row.names = FALSE)
Useful variables
# realm that combined Terrestrial and Freshwater, for interacting with human impact
trends[, REALM2 := REALM]
levels(trends$REALM2) = list(TerrFresh = "Freshwater", TerrFresh = "Terrestrial", Marine = "Marine")
# group Marine invertebrates/plants in with All
trends[, taxa_mod2 := taxa_mod]
trends[taxa_mod == 'Marine invertebrates/plants', taxa_mod2 := 'All']
Do the variables look ok?
Unscaled
# histograms to examine
cexmain = 0.6
par(mfrow = c(5,4))
invisible(trends[, hist(minyrBT, main = 'Start year', cex.main = cexmain)])
invisible(trends[, hist(maxyrBT - minyrBT, main = 'Duration (years)', cex.main = cexmain)])
invisible(trends[, hist(nyrBT, main = 'Number of sampled years', cex.main = cexmain)])
invisible(trends[, hist(mass_mean_weight, main = 'Mass (g)', cex.main = cexmain)])
invisible(trends[, hist(speed_mean_weight, main = 'Speed (km/hr)', cex.main = cexmain)])
invisible(trends[, hist(lifespan_mean_weight, main = 'Lifespan (yr)', cex.main = cexmain)])
invisible(trends[, hist(tempave_metab, main = 'Metabolic temperature (°C)', cex.main = cexmain)])
invisible(trends[, hist(consfrac, main = 'Consumers (fraction)', cex.main = cexmain)])
invisible(trends[, hist(endofrac, main = 'Endotherms (fraction)', cex.main = cexmain)])
invisible(trends[, hist(tempave, main = 'Environmental temperature (°C)', cex.main = cexmain)])
invisible(trends[, hist(temptrend, main = 'Temperature trend (°C/yr)', cex.main = cexmain)])
invisible(trends[, hist(seas, main = 'Seasonality (°C)', cex.main = cexmain)])
invisible(trends[, hist(microclim, main = 'Microclimates (°C)', cex.main = cexmain)])
invisible(trends[, hist(Nspp, main = 'Species richness', cex.main = cexmain)])
invisible(trends[, hist(thermal_bias, main = 'Thermal bias (°C)', cex.main = cexmain)])
invisible(trends[, hist(npp, main = 'Net primary productivity', cex.main = cexmain)])
invisible(trends[, hist(veg, main = 'Vegetation index', cex.main = cexmain)])
invisible(trends[, hist(human_bowler, main = 'Human impact score (Bowler)', cex.main = cexmain)])
invisible(trends[, hist(human_venter, main = 'Human impact score (Venter)', cex.main = cexmain)])
invisible(trends[, hist(human_halpern, main = 'Human impact score (Halpern)', cex.main = cexmain)])
Scaled
# histograms to examine
cexmain = 0.6
par(mfrow = c(5,4))
invisible(trends[, hist(tempave.sc, main = 'Environmental temperature (°C)', cex.main = cexmain)])
invisible(trends[, hist(tempave_metab.sc, main = 'Metabolic temperature (°C)', cex.main = cexmain)])
invisible(trends[, hist(seas.sc, main = 'Seasonality (°C)', cex.main = cexmain)])
invisible(trends[, hist(microclim.sc, main = 'log Microclimates (°C)', cex.main = cexmain)])
invisible(trends[, hist(temptrend.sc, main = 'Temperature trend (°C/yr)', cex.main = cexmain)])
invisible(trends[, hist(temptrend_abs.sc, main = 'abs(Temperature trend) (°C/yr)', cex.main = cexmain)])
invisible(trends[, hist(mass.sc, main = 'log Mass (g)', cex.main = cexmain)])
invisible(trends[, hist(speed.sc, main = 'log Speed (km/hr)', cex.main = cexmain)])
invisible(trends[, hist(lifespan.sc, main = 'log Lifespan (yr)', cex.main = cexmain)])
invisible(trends[, hist(consumerfrac.sc, main = 'Consumers (fraction)', cex.main = cexmain)])
invisible(trends[, hist(endothermfrac.sc, main = 'Endotherms (fraction)', cex.main = cexmain)])
invisible(trends[, hist(nspp.sc, main = 'log Species richness', cex.main = cexmain)])
invisible(trends[, hist(thermal_bias.sc, main = 'Thermal bias (°C)', cex.main = cexmain)])
invisible(trends[, hist(npp.sc, main = 'log Net primary productivity', cex.main = cexmain)])
invisible(trends[, hist(veg.sc, main = 'log Vegetation index', cex.main = cexmain)])
invisible(trends[, hist(human_bowler.sc, main = 'log Human impact score (Bowler)', cex.main = cexmain)])
invisible(trends[, hist(human_footprint.sc, main = 'log Human impact score (Venter & Halpern)', cex.main = cexmain)])
Check correlations among variables. Pearson’s r is on the lower diagonal.
panel.cor <- function(x, y, digits = 2, prefix = "", cex.cor, ...)
{
usr <- par("usr"); on.exit(par(usr))
par(usr = c(0, 1, 0, 1))
r <- cor(x, y, use = 'pairwise.complete.obs')
txt <- format(c(r, 0.123456789), digits = digits)[1]
txt <- paste0(prefix, txt)
if(missing(cex.cor)) cex.cor <- 0.8/strwidth(txt)
text(0.5, 0.5, txt) #, cex = cex.cor * r)
}
pairs(formula = ~ tempave.sc + tempave_metab.sc + seas.sc + microclim.sc + temptrend.sc + temptrend_abs.sc + mass.sc + speed.sc + lifespan.sc + consumerfrac.sc + endothermfrac.sc + nspp.sc + thermal_bias.sc + npp.sc + veg.sc + human_bowler.sc + human_footprint.sc, data = trends, gap = 1/10, cex = 0.2, col = '#00000022', lower.panel = panel.cor)
Mass and lifespan look tightly correlated, but r only 0.56…? Tempave_metab and lifespan don’t look tightly correlated, but r= -0.81 Tempave_metab and speed don’t look tightly correlated, but r= -0.83 Lifespan and speed don’t look tightly correlated, but r = 0.73
LS0tCnRpdGxlOiAiVHVybm92ZXIgY292YXJpYXRlIGRhdGEgcHJlcCIKb3V0cHV0OgogIGdpdGh1Yl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgpgYGB7ciBzZXR1cH0KbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoYmVhbnBsb3QpICMgZm9yIGJlYW5wbG90cwpsaWJyYXJ5KGdyaWRFeHRyYSkgIyB0byBjb21iaW5lIGdncGxvdHMgdG9nZXRoZXIKbGlicmFyeShncmlkKSAjIHRvIGNvbWJpbmUgZ2dwbG90cyB0b2dldGhlcgoKCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gcnByb2pyb290OjpmaW5kX3JzdHVkaW9fcm9vdF9maWxlKCkpICMgdGVsbCBSU3R1ZGlvIHRvIHVzZSBwcm9qZWN0IHJvb3QgZGlyZWN0b3J5IGFzIHRoZSByb290IGZvciB0aGlzIG5vdGVib29rLiBOZWVkZWQgc2luY2Ugd2UgYXJlIHN0b3JpbmcgY29kZSBpbiBhIHNlcGFyYXRlIGRpcmVjdG9yeS4KYGBgCgojIyMgTG9hZCBkYXRhCmBgYHtyIGxvYWQgZGF0YX0KIyBCaW9UaW1lCmxvYWQoJ2RhdGEvYmlvdGltZV9ibG93ZXMvYnRfbWFsaW4uUmRhdGEnKQpidCA8LSBkYXRhLnRhYmxlKGJ0X21hbGluKTsgcm0oYnRfbWFsaW4pCgojIFRlbXBlcmF0dXJlIGF2ZXJhZ2UsIHRyZW5kcywgYW5kIHNlYXNvbmFsaXR5CnRlbXBlcmF0dXJlIDwtIGZyZWFkKCdvdXRwdXQvdGVtcGVyYXR1cmVfYnlyYXJlZnlJRC5jc3YuZ3onKQoKIyBtaWNyb2NsaW1hdGVzCm1pY3JvY2xpbSA8LSBmcmVhZCgnb3V0cHV0L21pY3JvY2xpbWF0ZXMuY3N2Lmd6JywgZHJvcCA9IDEpCgojIE5QUApucHAgPC0gZnJlYWQoJ291dHB1dC9ucHBsYW5kb2NlYW4uY3N2Lmd6JykKCiMgQm9keSBzaXplCmJzIDwtIGZyZWFkKCdvdXRwdXQvbWFzc19ieXJhcmVmeWlkLmNzdi5neicsIGRyb3AgPSAxKQpic1ssICc6PScoU1RVRFlfSUQgPSBOVUxMLCBSRUFMTSA9IE5VTEwsIHRheGFfbW9kID0gTlVMTCldICMgcmVtb3ZlIHVubmVjZXNzYXJ5IGNvbHVtbnMgCgojIE1vYmlsaXR5CnNwZWVkIDwtIGZyZWFkKCdvdXRwdXQvc3BlZWRfYnlyYXJlZnlJRC5jc3YuZ3onLCBkcm9wID0gMSkKc3BlZWRbLCAnOj0nKFNUVURZX0lEID0gTlVMTCwgUkVBTE0gPSBOVUxMLCB0YXhhX21vZCA9IE5VTEwpXSAjIHJlbW92ZSB1bm5lY2Vzc2FyeSBjb2x1bW5zIAoKIyBMaWZlc3Bhbgpsc3AgPC0gZnJlYWQoJ291dHB1dC9saWZlc3Bhbl9ieXJhcmVmeUlELmNzdi5neicpCgojIENUSQpjdGkgPC0gZnJlYWQoJ291dHB1dC9jdGlfYnlyYXJlZnlJRC5jc3YuZ3onKQogICAgCiMgY29uc3VtZXIgdnMuIHByb2R1Y2VyCmNvbnNmcmFjIDwtIGZyZWFkKCdvdXRwdXQvY29uc2ZyYWNfYnlyYXJlZnlJRC5jc3YuZ3onKQoKIyByaWNobmVzcwpyaWNoIDwtIGZyZWFkKCdvdXRwdXQvcmljaG5lc3NfYnlfcmFyZWZ5SUQuY3N2Lmd6JykgIyBudW1iZXIgb2Ygc3BlY2llcwoKIyBlbmRvdGhlcm0gdnMuIGVjdG90aGVybQplbmRvZnJhYyA8LSBmcmVhZCgnb3V0cHV0L2VuZG9mcmFjX2J5cmFyZWZ5SUQuY3N2Lmd6JykgIyBlbmRvdGhlcm0gdnMuIGVjdG90aGVybSBjbGFzc2lmaWNhdGlvbnMKCiMgaHVtYW4gaW1wYWN0Cmh1bWFuIDwtIGZyZWFkKCdvdXRwdXQvaHVtYW5pbXBhY3RfYnlfcmFyZWZ5SUQuY3N2Lmd6JykKCiMgJXZlZwp2ZWcgPC0gYXMuZGF0YS50YWJsZShyZWFkUkRTKCdvdXRwdXQvdmN0X2J5X3JhcmVmeUlELnJkcycpKQp2ZWdbLCB2ZWcgOj0gKGB0cmVlIGNvdmVyICUgKG1lYW4pYCArIDAuNSAqIGBub24tdHJlZSB2ZWcuICUgKG1lYW4pYCkvMTAwXSAjIHZlZyBpbmRleCBmcm9tIDAgKGFsbCBub24tdmVnKSB0byAxIChhbGwgdHJlZSkuIE5vbi10cmVlIHZlZyBjb3VudHMgYXMgMC41LgpgYGAKCiMjIyBQbG90IGEgdHVybm92ZXIgZXhhbXBsZQpGaXJzdCBpcyBhIGxvbmcgdGltZS1zZXJpZXMsIG5leHQgb25lIHNob3dzIGFuIGV4YW1wbGUgcmVzdWx0IG9mIHJlbW92aW5nIHRoZSBmaXJzdCB5ZWFyIG9mIHNlbGYtY29tcGFyaXNvbi4KYGBge3IgcGxvdCB0dXJub3Zlcn0KI2J0WywgLihuID0gLk4pLCBieSA9IHJhcmVmeUlEXVtuID4gNTAsXQoKZ2dwbG90KGJ0W3JhcmVmeUlEID09ICczMzlfMTA4NTQ3NyddLCBhZXMoWUVBUiwgSnR1X2Jhc2UpKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJykgKwogICAgeGxhYignWWVhcicpICsgeWxhYignSmFjY2FyZCBkaXNzaW1pbGFyaXR5JykKCmdncGxvdChidFtyYXJlZnlJRCA9PSAnNDg5XzE2NzU0J10sIGFlcyhZRUFSLCBKdHVfYmFzZSkpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nLCBzZSA9IEZBTFNFKSArCiAgICB4bGFiKCdZZWFyJykgKyB5bGFiKCdKYWNjYXJkIGRpc3NpbWlsYXJpdHknKSArCiAgZ2VvbV9zbW9vdGgoZGF0YSA9IGJ0W3JhcmVmeUlEID09ICc0ODlfMTY3NTQnICYgWUVBUiAhPSAyMDAwXSwgbWV0aG9kID0gJ2xtJywgc2UgPSBGQUxTRSwgY29sb3IgPSAncmVkJykKYGBgCgojIyMgQXNzZW1ibGUgZGF0YXNldCBvZiBiZXRhIGRpdmVyc2l0eSB0cmVuZHMgKHRlbXBvcmFsIHR1cm5vdmVyKSBhbmQgY292YXJpYXRlcwpgYGB7ciBhc3NlbWJsZSB0cmVuZHMsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgY2FsY3VsYXRlIHRlbXBvcmFsIHR1cm5vdmVyCmNhbGN0cmVuZCA8LSBmdW5jdGlvbih5LCBZRUFSLCBubSA9ICd5Jyl7ICMgZnVuY3Rpb24gdG8gY2FsYyB0cmVuZHMKICAjIHR1cm4gb2ZmIHdhcm5pbmdzIGZvciB0aGUgZm9sbG93aW5nCiAgZGVmYXVsdFcgPC0gZ2V0T3B0aW9uKCJ3YXJuIikKICBvcHRpb25zKHdhcm4gPSAtMSkKICAKICBtb2QgPC0gbG0oeSB+IFlFQVIpCiAgb3V0IDwtIGxpc3QoeSA9IGNvZWYobW9kKVsyXSwgIyBjb2VmIGZvciB0aGUgc2xvcGUKICAgICAgICAgICAgICB5X3NlID0gc3FydChkaWFnKHZjb3YobW9kKSkpWzJdKSAjIFNFCiAgbmFtZXMob3V0KSA8LSBjKG5tLCBwYXN0ZTAobm0sICdfc2UnKSkKICBvcHRpb25zKHdhcm4gPSBkZWZhdWx0VykKICByZXR1cm4ob3V0KQp9CgojIGZ1bmN0aW9uIHRvIGNhbGMgdHJlbmRzLCByZW1vdmluZyBmaXJzdCB5ZWFyIHdpdGggMApjYWxjdHJlbmRyZW0wIDwtIGZ1bmN0aW9uKHksIFlFQVIsIG5tID0gJ3knKXsKICAjIHR1cm4gb2ZmIHdhcm5pbmdzIGZvciB0aGUgZm9sbG93aW5nCiAgZGVmYXVsdFcgPC0gZ2V0T3B0aW9uKCJ3YXJuIikKICBvcHRpb25zKHdhcm4gPSAtMSkKICAKICBpZihsZW5ndGgoWUVBUik+Mil7CiAgICBvIDwtIG9yZGVyKFlFQVIpCiAgICBZRUFSMiA8LSBZRUFSW29dWzI6bGVuZ3RoKFlFQVIpXQogICAgeTIgPC0geVtvXVsyOmxlbmd0aCh5KV0KICAgIAogICAgaWYoc3VtKCFpcy5uYSh5MikpID49IDIpeyAjIG1ha2Ugc3VyZSBlbm91Z2ggdmFsdWVzIHRvIGZpdCBhIGxpbmUKICAgICAgbW9kIDwtIGxtKHkyIH4gWUVBUjIpCiAgICAgIG91dCA8LSBsaXN0KHkgPSBjb2VmKG1vZClbMl0sICMgY29lZiBmb3IgdGhlIHNsb3BlCiAgICAgICAgICAgICAgICAgIHlfc2UgPSBzcXJ0KGRpYWcodmNvdihtb2QpKSlbMl0pICMgU0UKICAgICAgbmFtZXMob3V0KSA8LSBjKG5tLCBwYXN0ZTAobm0sICdfc2UnKSkKICAgICAgb3B0aW9ucyh3YXJuID0gZGVmYXVsdFcpCiAgICAgIHJldHVybihvdXQpCiAgICAgIAogICAgfSBlbHNlIHsKICAgICAgb3V0IDwtIGxpc3QoeSA9IE5BX3JlYWxfLCB5X3NlID0gTkFfcmVhbF8pCiAgICAgIG5hbWVzKG91dCkgPC0gYyhubSwgcGFzdGUwKG5tLCAnX3NlJykpCiAgICAgIAogICAgICBvcHRpb25zKHdhcm4gPSBkZWZhdWx0VykKICAgICAgcmV0dXJuKG91dCkKICAgIH0KICAgIAogIH0gZWxzZSB7CiAgICBvdXQgPC0gbGlzdCh5ID0gTkFfcmVhbF8sIHlfc2UgPSBOQV9yZWFsXykKICAgIG5hbWVzKG91dCkgPC0gYyhubSwgcGFzdGUwKG5tLCAnX3NlJykpCiAgCiAgICBvcHRpb25zKHdhcm4gPSBkZWZhdWx0VykKICAgIHJldHVybihvdXQpCiAgfQogIAoKfQoKY2FsY2ZpcnN0bGFzdCA8LSBmdW5jdGlvbih5LCBZRUFSLCBubSA9ICd5Jyl7ICMgZnVuY3Rpb24gdG8gZ2V0IGRpc3RhbmNlIGZyb20gbGFzdCB0byBmaXJzdCB5ZWFyCiAgIyB0dXJuIG9mZiB3YXJuaW5ncyBmb3IgdGhlIGZvbGxvd2luZwogIGRlZmF1bHRXIDwtIGdldE9wdGlvbigid2FybiIpCiAgb3B0aW9ucyh3YXJuID0gLTEpCiAgCiAgaWYobGVuZ3RoKFlFQVIpPjEpewogICAgbyA8LSBvcmRlcihZRUFSKQogICAgWUVBUjIgPC0gWUVBUltvXVsyOmxlbmd0aChZRUFSKV0KICAgIHkyIDwtIHlbb11bMjpsZW5ndGgoeSldCiAgICAKICAgIG91dCA8LSBsaXN0KHkgPSB5MltsZW5ndGgoeTIpXSwgIyBkaXNzaW1pbGFyaXR5IGZvciBsYXN0IHllYXIKICAgICAgICAgICAgICAgIHlfc2UgPSBOQV9yZWFsXykKICB9IGVsc2UgewogICAgb3V0IDwtIGxpc3QoeSA9IE5BX3JlYWxfLCB5X3NlID0gTkFfcmVhbF8pCiAgfQoKICBuYW1lcyhvdXQpIDwtIGMobm0sIHBhc3RlMChubSwgJ19zZScpKQogIG9wdGlvbnMod2FybiA9IGRlZmF1bHRXKQogIHJldHVybihvdXQpCn0KCgoKc2V0a2V5KGJ0LCBTVFVEWV9JRCwgcmFyZWZ5SUQsIFlFQVIpCgppZihmaWxlLmV4aXN0cygndGVtcC90cmVuZHN0ZW1wLnJkcycpKXsKICB0cmVuZHMgPC0gcmVhZFJEUygndGVtcC90cmVuZHN0ZW1wLnJkcycpCn0gZWxzZSB7CiAgCiAgdHJlbmRzMSA8LSBidFssIGNhbGN0cmVuZChKdHVfYmFzZSwgWUVBUiwgJ0p0dXRyZW5kJyksCiAgICAgICAgICAgICAgICBieSA9IC4oUkVBTE0sIEJpb21lLCB0YXhhX21vZCwgU1RVRFlfSUQsIHJhcmVmeUlELCByYXJlZnlJRF94LCByYXJlZnlJRF95KV0gIyBjYWxjdWxhdGUgdHJlbmQgaW4gSmFjY2FyZCB0dXJub3ZlciBmcm9tIGZpcnN0IHllYXIsIHBsdXMgU0VzCiAgdHJlbmRzMiA8LSBidFssIGNhbGN0cmVuZChKYmV0YV9iYXNlLCBZRUFSLCAnSmJldGF0cmVuZCcpLAogICAgICAgICAgICAgICAgYnkgPSAuKHJhcmVmeUlEKV0gIyBjYWxjdWxhdGUgdHJlbmQgaW4gdG90YWwgSmFjY2FyZCcgYmV0YSBkaXZlcnNpdHkncyBmcm9tIGZpcnN0IHllYXIsCiAgdHJlbmRzMyA8LSBidFssIGNhbGN0cmVuZCgxLUhvcm5fYmFzZSwgWUVBUiwgJ0hvcm50cmVuZCcpLAogICAgICAgICAgICAgICAgYnkgPSAuKHJhcmVmeUlEKV0gIyBjYWxjdWxhdGUgdHJlbmQgaW4gSG9ybi1Nb3Jpc2l0YSBmcm9tIGZpcnN0IHllYXIuIENvbnZlcnQgdG8gZGlzc2ltaWxhcml0eS4KICB0cmVuZHM0IDwtIGJ0WywgLihTdHJlbmQgPSBjb2VmKGxtKEkobG9nKFMpKSB+IFlFQVIpKVsyXSksIGJ5ID0gLihyYXJlZnlJRCldICMgdHJlbmQgaW4gbG9nKFMpCiAgCiAgdHJlbmRzNSA8LSBidFssIGNhbGN0cmVuZHJlbTAoSnR1X2Jhc2UsIFlFQVIsICdKdHV0cmVuZHJlbTAnKSwgCiAgICAgICAgICAgICAgICBieSA9IC4ocmFyZWZ5SUQpXSAjIGNhbGN1bGF0ZSB0cmVuZCBpbiBKYWNjYXJkIHR1cm5vdmVyIHdpdGhvdXQgZmlyc3QgeWVhcgogIHRyZW5kczYgPC0gYnRbLCBjYWxjdHJlbmRyZW0wKEpiZXRhX2Jhc2UsIFlFQVIsICdKYmV0YXRyZW5kcmVtMCcpLAogICAgICAgICAgICAgICAgYnkgPSAuKHJhcmVmeUlEKV0KICB0cmVuZHM3IDwtIGJ0WywgY2FsY3RyZW5kcmVtMCgxLUhvcm5fYmFzZSwgWUVBUiwgJ0hvcm50cmVuZHJlbTAnKSwKICAgICAgICAgICAgICAgIGJ5ID0gLihyYXJlZnlJRCldCiAgCiAgdHJlbmRzOCA8LSBidFssIGNhbGNmaXJzdGxhc3QoSnR1X2Jhc2UsIFlFQVIsICdKdHVsYXN0JyksCiAgICAgICAgICAgICAgICBieSA9IC4ocmFyZWZ5SUQpXQogIHRyZW5kczkgPC0gYnRbLCBjYWxjZmlyc3RsYXN0KEpiZXRhX2Jhc2UsIFlFQVIsICdKYmV0YWxhc3QnKSwKICAgICAgICAgICAgICAgIGJ5ID0gLihyYXJlZnlJRCldCiAgdHJlbmRzMTAgPC0gYnRbLCBjYWxjZmlyc3RsYXN0KDEtSG9ybl9iYXNlLCBZRUFSLCAnSG9ybmxhc3QnKSwKICAgICAgICAgICAgICAgICBieSA9IC4ocmFyZWZ5SUQpXQogIAogIAogIG55ckJUIDwtICBidFssIC4obnlyQlQgPSBsZW5ndGgoWUVBUiksCiAgICAgICAgICAgICAgICAgICBtaW55ckJUID0gbWluKFlFQVIpLAogICAgICAgICAgICAgICAgICAgbWF4eXJCVCA9IG1heChZRUFSKSwKICAgICAgICAgICAgICAgICAgIG1lZGlhbnlyQlQgPSBtZWRpYW4oWUVBUiksCiAgICAgICAgICAgICAgICAgICBtZWFueXJCVCA9IG1lYW4oWUVBUikpLAogICAgICAgICAgICAgICBieSA9IC4ocmFyZWZ5SUQpXSAjIG51bWJlciBvZiB5ZWFycyBpbiB0aW1lLXNlcmllcwogIAogIHRyZW5kcyA8LSBtZXJnZSh0cmVuZHMxLCB0cmVuZHMyKSAjIG1lcmdlIGluIHRvdGFsIEogYW5kIEhvcm4tTW9yaXNpdGEKICB0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCB0cmVuZHMzKQogIHRyZW5kcyA8LSBtZXJnZSh0cmVuZHMsIHRyZW5kczUpCiAgdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgdHJlbmRzNikKICB0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCB0cmVuZHM3KQogIHRyZW5kcyA8LSBtZXJnZSh0cmVuZHMsIHRyZW5kczgpCiAgdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgdHJlbmRzOSkKICB0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCB0cmVuZHMxMCkKICB0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCBueXJCVCkKICAKICBzYXZlUkRTKHRyZW5kcywgZmlsZSA9ICd0ZW1wL3RyZW5kc3RlbXAucmRzJykKICAKfQpgYGAKCkFkZCBjb3ZhcmlhdGVzCmBgYHtyIGFkZCBjb3ZhcmlhdGUgZGF0YX0KIyBhZGQgY292YXJpYXRlcwp0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCB0ZW1wZXJhdHVyZVssIC4ocmFyZWZ5SUQsIHRlbXBhdmUsIHRlbXBhdmVfbWV0YWIsIHRlbXB0cmVuZCwgc2VhcyldLCBhbGwueCA9IFRSVUUsIGJ5ID0gJ3JhcmVmeUlEJykgIyB0ZW1wZXJhdHVyZSBhdmUsIGF2ZSBtZXRhYm9saWMsIHRyZW5kLCBhbmQgc2Vhc29uYWxpdHkKdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgbWljcm9jbGltWywgLihyYXJlZnlJRCwgbWljcm9jbGltID0gVGVtcF9zZDIwa20pXSwgYWxsLnggPSBUUlVFLCBieSA9ICdyYXJlZnlJRCcpICMgbWljcm9jbGltYXRlcwp0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCBucHAsIGFsbC54ID0gVFJVRSwgYnkgPSAncmFyZWZ5SUQnKSAjIG5wcAp0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCBic1ssIC4ocmFyZWZ5SUQsIG1hc3NfbWVhbl93ZWlnaHQsIG1hc3Nfc2Rfd2VpZ2h0KV0sIGFsbC54ID0gVFJVRSkgIyBib2R5IHNpemUgbWFzcyAoZykKdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgc3BlZWRbLCAuKHJhcmVmeUlELCBzcGVlZF9tZWFuX3dlaWdodCwgc3BlZWRfc2Rfd2VpZ2h0KV0sIGFsbC54ID0gVFJVRSkgIyBzcGVlZCAoa20vaHIpCnRyZW5kcyA8LSBtZXJnZSh0cmVuZHMsIGxzcFssIC4ocmFyZWZ5SUQsIGxpZmVzcGFuX21lYW5fd2VpZ2h0LCBsaWZlc3Bhbl9zZF93ZWlnaHQpXSwgYWxsLnggPSBUUlVFKSAjIGxpZmVzcGFuICh5cikKdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgY3RpWywgLihyYXJlZnlJRCwgdGhlcm1hbF9iaWFzKV0sIGFsbC54ID0gVFJVRSkgIyB0aGVybWFsIGJpYXMgKGRlZ0MpCnRyZW5kcyA8LSBtZXJnZSh0cmVuZHMsIGNvbnNmcmFjWywgLihyYXJlZnlJRCwgY29uc2ZyYWMpXSwgYWxsLnggPSBUUlVFKSAjIGZyYWN0aW9uIGNvbnN1bWVycwp0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCByaWNoLCBhbGwueCA9IFRSVUUpICMgc3BlY2llcyByaWNobmVzcwp0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCBlbmRvZnJhY1ssIC4ocmFyZWZ5SUQsIGVuZG9mcmFjKV0sIGFsbC54ID0gVFJVRSkgIyBlbmRvdGhlcm0gdnMuIGVjdG90aGVybQp0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCBodW1hblssIC4ocmFyZWZ5SUQsIGh1bWFuX2Jvd2xlciA9IGF0YywgaHVtYW5fdmVudGVyID0gaGZwLCBodW1hbl9oYWxwZXJuID0gaGltcCldLCBhbGwueCA9IFRSVUUpICMgaHVtYW4gaW1wYWN0CnRyZW5kcyA8LSBtZXJnZSh0cmVuZHMsIHZlZ1ssIC4ocmFyZWZ5SUQsIHZlZyA9IHZlZyldLCBhbGwueCA9IFRSVUUpICMgdmVnZXRhdGlvbiBpbmRleAp0cmVuZHNbUkVBTE0gPT0gJ01hcmluZScsIHZlZyA6PSAwXSAjIHZlZyBpbmRleCBpcyAwIGF0IHNlYQpgYGAKCiMjIyBEbyBzb21lIGJhc2ljIGNoZWNrcyBvZiB0aGUgdHVybm92ZXIgY2FsY3VsYXRpb25zCiMjIyMgSGlzdG9ncmFtcyBvZiB0ZW1wb3JhbCBjaGFuZ2UKYGBge3IgaGlzdG9ncmFtcyBvZiBjaGFuZ2UsIG1lc3NhZ2VzID0gRkFMU0V9CiMgYmFzaWMgY2hlY2tzCnRyZW5kcwoKeCA8LSB0cmVuZHNbLCBoaXN0KEp0dXRyZW5kKV0KeCA8LSB0cmVuZHNbLCBoaXN0KEpiZXRhdHJlbmQpXQp4IDwtIHRyZW5kc1ssIGhpc3QoSG9ybnRyZW5kKV0KCnggPC0gdHJlbmRzWywgaGlzdChKdHV0cmVuZHJlbTApXQp4IDwtIHRyZW5kc1ssIGhpc3QoSmJldGF0cmVuZHJlbTApXQp4IDwtIHRyZW5kc1ssIGhpc3QoSG9ybnRyZW5kcmVtMCldCgp4IDwtIHRyZW5kc1ssIGhpc3QoSnR1bGFzdCldCnggPC0gdHJlbmRzWywgaGlzdChKYmV0YWxhc3QpXQp4IDwtIHRyZW5kc1ssIGhpc3QoSG9ybmxhc3QpXQoKYGBgCgojIyMjIENoYW5nZSBjb21wYXJlZCB0byBudW1iZXIgb2YgeWVhcnMgaW4gdGltZS1zZXJpZXMKYGBge3IgY2hhbmdlIHZzLiBudW0geWVhcnN9CiMgbnVtYmVyIG9mIHllYXIKdHJlbmRzWywgc3VtbWFyeShueXJCVCldCnggPC0gdHJlbmRzWywgaGlzdChueXJCVCldCnRyZW5kc1ssIHBsb3QobnlyQlQsIEp0dXRyZW5kLCBsb2cgPSAneCcsIGNvbCA9ICcjMDAwMDAwMzMnKV0KdHJlbmRzWywgcGxvdChueXJCVCwgSnR1dHJlbmRyZW0wLCBsb2cgPSAneCcsIGNvbCA9ICcjMDAwMDAwMzMnKV0KdHJlbmRzWywgcGxvdChueXJCVCwgSnR1bGFzdCwgbG9nID0gJ3gnLCBjb2wgPSAnIzAwMDAwMDMzJyldCmBgYAoKIyMjIyBDaGFuZ2UgY29tcGFyZWQgdG8gbnVtYmVyIG9mIHNwZWNpZXMgaW4gdGltZS1zZXJpZXMKYGBge3IgY2hhbmdlIHZzLiBudW1iZXIgb2Ygc3BlY2llc30KIyBudW1iZXIgb2Ygc3BlY2llcwp0cmVuZHNbLCBzdW1tYXJ5KE5zcHApXQp4IDwtIHRyZW5kc1ssIGhpc3QoTnNwcCldCnRyZW5kc1ssIHBsb3QoTnNwcCwgSnR1dHJlbmQsIGxvZyA9ICd4JywgY29sID0gJyMwMDAwMDAzMycpXQp0cmVuZHNbLCBwbG90KE5zcHAsIEp0dXRyZW5kcmVtMCwgbG9nID0gJ3gnLCBjb2wgPSAnIzAwMDAwMDMzJyldCnRyZW5kc1ssIHBsb3QoTnNwcCwgSnR1bGFzdCwgbG9nID0gJ3gnLCBjb2wgPSAnIzAwMDAwMDMzJyldCmBgYAoKUmVtb3ZlIHN0dWRpZXMgd2l0aCBvbmx5IDEgc3BlY2llcwpgYGB7ciByZW1vdmUgMS1zcHAgc3R1ZGllc30KbnJvdyh0cmVuZHMpCnRyZW5kcyA8LSB0cmVuZHNbTnNwcCA+IDEsIF0KbnJvdyh0cmVuZHMpCmBgYAoKVHVybm92ZXIgY2FsY3VsYXRpb25zIGFyZSBjb3JyZWxhdGVkLCB0aG91Z2ggbGVzcyBzbyBmb3IgSG9ybgpgYGB7ciBiYXNpYyBwYWlyd2lzZSBncmFwaHMgb2YgdHVybm92ZXIgbWV0cmljc30KIyBhcmUgdHVybm92ZXIgY2FsY3VsYXRpb25zIGNvcnJlbGF0ZWQ/CmdncGxvdCh0cmVuZHMsIGFlcyhKYmV0YXRyZW5kcmVtMCwgSnR1dHJlbmRyZW0wKSkgKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykgKwogICAgZ2VvbV9zbW9vdGgoKQoKZ2dwbG90KHRyZW5kcywgYWVzKEpiZXRhdHJlbmRyZW0wLCBIb3JudHJlbmRyZW0wKSkgKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykgKwogICAgZ2VvbV9zbW9vdGgoKQoKYGBgCgoKVGVtcG9yYWwgdHVybm92ZXIgaXMgbm90IGFsbCB0aGF0IGNvcnJlbGF0ZWQgYmV0d2VlbiBpbmNsdWRpbmcgZmlyc3QgeWVhciBvciBub3QuCmBgYHtyIHR1cm5vdmVyIG1ldHJpY3Mgd2l0aCBhbmQgd2l0aG91dCBmaXJzdCB5ZWFyfQpnZ3Bsb3QodHJlbmRzLCBhZXMoSnR1dHJlbmQsIEp0dXRyZW5kcmVtMCkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC4zKSArCiAgZ2VvbV9zbW9vdGgoKSArCiAgZ2VvbV9hYmxpbmUoYSA9IDAsIGIgPSAxKQoKZ2dwbG90KHRyZW5kcywgYWVzKEpiZXRhdHJlbmQsIEpiZXRhdHJlbmRyZW0wKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjMpICsKICBnZW9tX3Ntb290aCgpICsKICBnZW9tX2FibGluZShhID0gMCwgYiA9IDEpCgpnZ3Bsb3QodHJlbmRzLCBhZXMoSG9ybnRyZW5kLCBIb3JudHJlbmRyZW0wKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjMpICsKICBnZW9tX3Ntb290aCgpICsKICBnZW9tX2FibGluZShhID0gMCwgYiA9IDEpCgpgYGAKCiMjIENvbXBhcmUgY292YXJpYXRlcyBhY3Jvc3MgcmVhbG1zCmBgYHtyIGNvbXBhcmUgYWNyb3NzIHJlYWxtcywgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTl9CmkgPC0gdHJlbmRzWywgIWR1cGxpY2F0ZWQocmFyZWZ5SUQpXTsgc3VtKGkpCnBhcihtZnJvdz1jKDUsMykpCmJlYW5wbG90KHJhcmVmeUlEX3kgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnTGF0aXR1ZGUgKGRlZ04pJywgbGwgPSAwLjA1KQpiZWFucGxvdCh0ZW1wYXZlIH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ1RlbXBlcmF0dXJlIChkZWdDKScsIGxsID0gMC4wNSkKYmVhbnBsb3QodGVtcGF2ZV9tZXRhYiB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2ksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdNZXRhYm9saWMgVGVtcGVyYXR1cmUgKGRlZ0MpJywgbGwgPSAwLjA1LCBidyA9ICducmQwJykgIyBucmQwIGJhbmR3aWR0aCB0byBjYWxjdWxhdGlvbiBnYXAKYmVhbnBsb3Qoc2VhcyB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2ksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdTZWFzb25hbGl0eSAoZGVnQyknLCBsbCA9IDAuMDUpCmJlYW5wbG90KG1pY3JvY2xpbSB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2ksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdNaWNyb2NsaW1hdGVzIChkZWdDKScsIGxsID0gMC4wNSkKYmVhbnBsb3QodGVtcHRyZW5kIH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ1RlbXBlcmF0dXJlIHRyZW5kIChkZWdDL3lyKScsIGxsID0gMC4wNSkKYmVhbnBsb3QobWFzc19tZWFuX3dlaWdodCB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2ksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdNYXNzIChnKScsIGxsID0gMC4wNSwgbG9nID0gJ3knKQpiZWFucGxvdChzcGVlZF9tZWFuX3dlaWdodCArMSB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2ksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdTcGVlZCAoa20vaHIpJywgbGwgPSAwLjA1LCBsb2cgPSAneScpCmJlYW5wbG90KGxpZmVzcGFuX21lYW5fd2VpZ2h0IH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ0xpZmVzcGFuICh5ciknLCBsbCA9IDAuMDUsIGxvZyA9ICd5JykKI2JlYW5wbG90KGNvbnNmcmFjIH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ0NvbnN1bWVycyAoZnJhY3Rpb24pJywgbGwgPSAwLjA1LCBsb2cgPSAnJykgIyB0b28gc3BhcnNlCiNiZWFucGxvdChlbmRvZnJhYyB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2ksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdFbmRvdGhlcm1zIChmcmFjdGlvbiknLCBsbCA9IDAuMDUsIGxvZyA9ICcnKSAjIHRvbyBzcGFyc2UKYmVhbnBsb3QoTnNwcCB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2ksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdOdW1iZXIgb2Ygc3BlY2llcycsIGxsID0gMC4wNSwgbG9nID0gJ3knKQpiZWFucGxvdCh0aGVybWFsX2JpYXMgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpICYgIWlzLm5hKHRoZXJtYWxfYmlhcyksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdUaGVybWFsIGJpYXMgKGRlZ0MpJywgbGwgPSAwLjA1KQpiZWFucGxvdChucHAgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnTlBQJywgbGwgPSAwLjA1KQpiZWFucGxvdCh2ZWcgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpICYgUkVBTE0gIT0nTWFyaW5lJyxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ05QUCcsIGxsID0gMC4wNSkKCmBgYAoKTWFyaW5lIGFyZSBpbiBnZW5lcmFsbHkgd2FybWVyIGxvY2F0aW9ucyAoc2Vhd2F0ZXIgZG9lc24ndCBmcmVlemUpCk1hcmluZSBoYXZlIG11Y2ggbG93ZXIgc2Vhc29uYWxpdHkuCk1hcmluZSBhbmQgZnJlc2h3YXRlciBoYXZlIHNvbWUgdmVyeSBzbWFsbCBtYXNzZXMgKHBsYW5rdG9uKSwgYnV0IG11Y2ggb2YgZGF0YXNldCBpcyBzaW1pbGFyIHRvIHRlcnJlc3RyaWFsLgpNYXJpbmUgaGFzIGEgbG90IG9mIHNsb3csIGNyYXdsaW5nIG9yZ2FuaXNtcywgYnV0IGxhbmQgaGFzIHBsYW50cy4gTGFuZCBhbHNvIGhhcyBiaXJkcyAoZmFzdCkuCgoKCgoKCiMjIFBsb3QgdHVybm92ZXIgdnMuIHRlbXBlcmF0dXJlCmBgYHtyIHBsb3QgdHVybm92ZXIgdnMgdGVtcCB0cmVuZCwgZWNobz1GQUxTRSwgZmlnLmhlaWdodCA9IDgsIGZpZy53aWR0aCA9IDksfQpwMSA8LSBnZ3Bsb3QodHJlbmRzLCBhZXModGVtcHRyZW5kLCBKdHV0cmVuZCwgY29sb3IgPSBSRUFMTSwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnVGVtcGVyYXR1cmUgdHJlbmQgKMKwQy95ciknLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnLCB0aXRsZSA9ICdBbGwnKQoKIyBKYWNjYXJkIHRvdGFsIHRyZW5kIHZzLiB0ZW1wZXJhdHVyZSB0cmVuZCAoYWNyb3NzIGFsbCB5ZWFycykKcDIgPC0gZ2dwbG90KHRyZW5kcywgYWVzKHRlbXB0cmVuZCwgSmJldGF0cmVuZCwgY29sb3IgPSBSRUFMTSwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnVGVtcGVyYXR1cmUgdHJlbmQgKMKwQy95ZWFyKScsIHkgPSAnSmFjY2FyZCB0b3RhbCB0ZW1wb3JhbCB0cmVuZCcpCgojIEhvcm4tTW9yaXNpdGEgdHVybm92ZXIgdHJlbmQgdnMuIHRlbXBlcmF0dXJlIHRyZW5kIChhY3Jvc3MgYWxsIHllYXJzKQpwMyA8LSBnZ3Bsb3QodHJlbmRzLCBhZXModGVtcHRyZW5kLCBIb3JudHJlbmQsIGNvbG9yID0gUkVBTE0sIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIpLCBuYS5ybSA9IFRSVUUpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgbGFicyh4ID0gJ1RlbXBlcmF0dXJlIHRyZW5kICjCsEMveWVhciknLCB5ID0gJ01vcmlzaXRhLUhvcm4gdGVtcG9yYWwgdHVybm92ZXInKQoKIyBzYW1lLCBidXQgb25seSB0cyA+PSA1IHlycwpwNCA8LSBnZ3Bsb3QodHJlbmRzW255ckJUID49IDUsIF0sIGFlcyh0ZW1wdHJlbmQsIEp0dXRyZW5kLCBjb2xvciA9IFJFQUxNLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIGxhYnMoeCA9ICdUZW1wZXJhdHVyZSB0cmVuZCAowrBDL3lyKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcsIHRpdGxlID0gJz49IDUgeXJzJykKCnA1IDwtIGdncGxvdCh0cmVuZHNbbnlyQlQgPj0gNSwgXSwgYWVzKHRlbXB0cmVuZCwgSmJldGF0cmVuZCwgY29sb3IgPSBSRUFMTSwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnVGVtcGVyYXR1cmUgdHJlbmQgKMKwQy95ZWFyKScsIHkgPSAnSmFjY2FyZCB0b3RhbCB0ZW1wb3JhbCB0cmVuZCcpCgpwNiA8LSBnZ3Bsb3QodHJlbmRzW255ckJUID49IDUsIF0sIGFlcyh0ZW1wdHJlbmQsIEhvcm50cmVuZCwgY29sb3IgPSBSRUFMTSwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnVGVtcGVyYXR1cmUgdHJlbmQgKMKwQy95ZWFyKScsIHkgPSAnTW9yaXNpdGEtSG9ybiB0ZW1wb3JhbCB0dXJub3ZlcicpCgojIHNhbWUsIGJ1dCByZW1vdmluZyB5ZWFyIDEKcDcgPC0gZ2dwbG90KHRyZW5kcywgYWVzKHRlbXB0cmVuZCwgSnR1dHJlbmRyZW0wLCBjb2xvciA9IFJFQUxNLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIGxhYnMoeCA9ICdUZW1wZXJhdHVyZSB0cmVuZCAowrBDL3lyKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCB3L291dCB5ZWFyIDEnLCB0aXRsZSA9ICdXaXRob3V0IHllYXIgMScpCgpwOCA8LSBnZ3Bsb3QodHJlbmRzLCBhZXModGVtcHRyZW5kLCBKYmV0YXRyZW5kcmVtMCwgY29sb3IgPSBSRUFMTSwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnVGVtcGVyYXR1cmUgdHJlbmQgKMKwQy95ZWFyKScsIHkgPSAnSmFjY2FyZCB0b3RhbCB0ZW1wb3JhbCB0cmVuZCB3L291dCB5ZWFyIDEnKQoKcDkgPC0gZ2dwbG90KHRyZW5kcywgYWVzKHRlbXB0cmVuZCwgSG9ybnRyZW5kcmVtMCwgY29sb3IgPSBSRUFMTSwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnVGVtcGVyYXR1cmUgdHJlbmQgKMKwQy95ZWFyKScsIHkgPSAnTW9yaXNpdGEtSG9ybiB0ZW1wb3JhbCB0dXJub3ZlciB3L291dCB5ZWFyIDEnKQoKCmdyaWQuYXJyYW5nZShwMSwgcDQsIHA3LCBwMiwgcDUsIHA4LCBwMywgcDYsIHA5LCBuY29sID0gMykKYGBgCgojIyMgVGltZS1zZXJpZXMgbGVuZ3RoIGFuZCB0ZW1wZXJhdHVyZSB0cmVuZD8KYGBge3IgdHMgbGVuZ3RoIGFuZCB0ZW1wIHRyZW5kfQpnZ3Bsb3QodHJlbmRzLCBhZXModGVtcHRyZW5kLCBueXJCVCkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKCkgKwogIHNjYWxlX3lfbG9nMTAoKQpgYGAKCiMjIFBsb3QgdHVybm92ZXIgdnMuIGV4cGxhbmF0b3J5IHZhcmlhYmxlcwpMaW5lcyBhcmUgZ2dwbG90IHNtb290aGVyIGZpdHMuCmBgYHtyIHBsb3QgdHVybm92ZXIgdiBleHBsYW5hdG9yeSB2YXJzLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0ID0gMTYsIGZpZy53aWR0aCA9IDksfQoKcDEgPC0gZ2dwbG90KHRyZW5kcywgYWVzKFJFQUxNLCBKdHV0cmVuZCkpICsKICBnZW9tX2JveHBsb3QobmEucm0gPSBUUlVFKSArIAogIGxhYnMoeCA9ICdSZWFsbScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwMiA8LSBnZ3Bsb3QodHJlbmRzLCBhZXModGVtcGF2ZSwgSnR1dHJlbmQsIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFJFQUxNKSwgc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSwgY29sb3IgPSAnYmxhY2snKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIGxhYnMoeCA9ICdUZW1wZXJhdHVyZSAowrBDKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwMyA8LSBnZ3Bsb3QodHJlbmRzLCBhZXModGVtcGF2ZV9tZXRhYiwgSnR1dHJlbmQsIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFJFQUxNKSwgc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSwgY29sb3IgPSAnYmxhY2snKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIGxhYnMoeCA9ICdNZXRhYm9saWMgdGVtcGVyYXR1cmUgKMKwQyknLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDQgPC0gZ2dwbG90KHRyZW5kcywgYWVzKHNlYXMsIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIpLCBuYS5ybSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnU2Vhc29uYWxpdHkgKMKwQyknLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDUgPC0gZ2dwbG90KHRyZW5kcywgYWVzKG1pY3JvY2xpbSwgSnR1dHJlbmQsIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFJFQUxNKSwgc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSwgY29sb3IgPSAnYmxhY2snKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIHNjYWxlX3hfbG9nMTAoKSArCiAgbGFicyh4ID0gJ01pY3JvY2xpbWF0ZSBhdmFpbGFiaWxpdHkgKMKwQyknLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDYgPC0gZ2dwbG90KHRyZW5kcywgYWVzKG1hc3NfbWVhbl93ZWlnaHQsIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIpLCBuYS5ybSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBzY2FsZV94X2xvZzEwKCkgKwogIGxhYnMoeCA9ICdNYXNzIChnKSknLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDcgPC0gZ2dwbG90KHRyZW5kcywgYWVzKHNwZWVkX21lYW5fd2VpZ2h0KzEsIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIpLCBuYS5ybSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBzY2FsZV94X2xvZzEwKCkgKwogIGxhYnMoeCA9ICdTcGVlZCAoa20gLyBocikpJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnA4IDwtIGdncGxvdCh0cmVuZHMsIGFlcyhsaWZlc3Bhbl9tZWFuX3dlaWdodCwgSnR1dHJlbmQsIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFJFQUxNKSwgc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSwgY29sb3IgPSAnYmxhY2snKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIHNjYWxlX3hfbG9nMTAoKSArCiAgbGFicyh4ID0gJ0xpZmVzcGFuICh5cikpJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnA5IDwtIGdncGxvdCh0cmVuZHMsIGFlcyhjb25zZnJhYywgSnR1dHJlbmQsIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFJFQUxNKSwgc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiwgayA9IDMpLCBuYS5ybSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnRnJhY3Rpb24gY29uc3VtZXJzJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnAxMCA8LSBnZ3Bsb3QodHJlbmRzLCBhZXMoZW5kb2ZyYWMsIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIsIGsgPSAzKSwgbmEucm0gPSBUUlVFLCBjb2xvciA9ICdibGFjaycpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgbGFicyh4ID0gJ0ZyYWN0aW9uIGVuZG90aGVybXMnLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDExIDwtIGdncGxvdCh0cmVuZHMsIGFlcyhOc3BwLCBKdHV0cmVuZCwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUkVBTE0pLCBzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFLCBjb2xvciA9ICdibGFjaycpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgc2NhbGVfeF9sb2cxMCgpICsKICBsYWJzKHggPSAnTnVtYmVyIG9mIHNwZWNpZXMnLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDEyIDwtIGdncGxvdCh0cmVuZHMsIGFlcyh0aGVybWFsX2JpYXMsIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIpLCBuYS5ybSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnVGhlcm1hbCBiaWFzICjCsEMpJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnAxMyA8LSBnZ3Bsb3QodHJlbmRzLCBhZXMobnBwLCBKdHV0cmVuZCwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUkVBTE0pLCBzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFLCBjb2xvciA9ICdibGFjaycpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgc2NhbGVfeF9sb2cxMCgpICsKICBsYWJzKHggPSAnTmV0IHByaW1hcnkgcHJvZHVjdGl2aXR5IChtZyBDIC8gbTIgLyBkYXkpJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnAxNCA8LSBnZ3Bsb3QodHJlbmRzLCBhZXModmVnLCBKdHV0cmVuZCwgY29sb3IgPSBSRUFMTSwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiwgayA9IDUpLCBuYS5ybSA9IFRSVUUpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgbGFicyh4ID0gJ1ZlZ2V0YXRpb24gc2NvcmUnLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDE1IDwtIGdncGxvdCh0cmVuZHMsIGFlcyhodW1hbl9ib3dsZXIsIEp0dXRyZW5kLCBjb2xvciA9IFJFQUxNLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiLCBrID0gNSksIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnQm93bGVyIGh1bWFuIGltcGFjdCBzY29yZScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwMTYgPC0gZ2dwbG90KHRyZW5kcywgYWVzKGh1bWFuX3ZlbnRlciwgSnR1dHJlbmQsIGNvbG9yID0gUkVBTE0sIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIsIGsgPSA1KSwgbmEucm0gPSBUUlVFKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIGxhYnMoeCA9ICdzY2FsZWQgSHVtYW4gaW1wYWN0IHNjb3JlIChWZW50ZXIpJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnAxNyA8LSBnZ3Bsb3QodHJlbmRzLCBhZXMoaHVtYW5faGFscGVybiwgSnR1dHJlbmQsIGNvbG9yID0gUkVBTE0sIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIsIGsgPSA1KSwgbmEucm0gPSBUUlVFKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIGxhYnMoeCA9ICdzY2FsZWQgSHVtYW4gaW1wYWN0IHNjb3JlIChIYWxwZXJuKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgoKZ3JpZC5hcnJhbmdlKHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIHA3LCBwOCwgcDksIHAxMCwgcDExLCBwMTIsIHAxMywgcDE0LCBwMTUsIHAxNiwgcDE3LCBuY29sID0gMikKYGBgCgpTdHJvbmcgdHJlbmRzIHdpdGggdGVtcGVyYXR1cmUgY2hhbmdlLCBidXQgdHJlbmRzIGFyZSBwcmV0dHkgc3ltbWV0cmljIGFyb3VuZCBubyB0cmVuZCBpbiB0ZW1wZXJhdHVyZSwgd2hpY2ggaW1wbGllcyB3YXJtaW5nIG9yIGNvb2xpbmcgZHJpdmVzIHNpbWlsYXIgZGVncmVlIG9mIGNvbW11bml0eSB0dXJub3Zlci4KU29tZSBpbmRpY2F0aW9uIG9mIGxlc3MgdHVybm92ZXIgZm9yIGxhcmdlciBvcmdhbmlzbXMgKG1hc3MpCkhpZ2hlciB0dXJub3ZlciBvbiBsYW5kIHdpdGggaGlnaGVyIHNlYXNvbmFsaXR5PwpNb3JlIHR1cm5vdmVyIGZvciBzaG9ydGVyLWxpdmVkIG9yZ2FuaXNtcz8KTm8gcmVhbGx5IGNsZWFyIGRpZmZlcmVuY2VzIGFtb25nIHJlYWxtcy4KCiMjIyBXcml0ZSBvdXQKYGBge3Igd3JpdGUgb3V0fQp3cml0ZS5jc3YodHJlbmRzLCBnemZpbGUoJ291dHB1dC90dXJub3Zlcl93X2NvdmFyaWF0ZXMuY3N2Lmd6JyksIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCgojIyMgVXNlZnVsIHZhcmlhYmxlcwpgYGB7ciB1c2VmdWwgdmFyc30KIyByZWFsbSB0aGF0IGNvbWJpbmVkIFRlcnJlc3RyaWFsIGFuZCBGcmVzaHdhdGVyLCBmb3IgaW50ZXJhY3Rpbmcgd2l0aCBodW1hbiBpbXBhY3QKdHJlbmRzWywgUkVBTE0yIDo9IFJFQUxNXQpsZXZlbHModHJlbmRzJFJFQUxNMikgPSBsaXN0KFRlcnJGcmVzaCA9ICJGcmVzaHdhdGVyIiwgVGVyckZyZXNoID0gIlRlcnJlc3RyaWFsIiwgTWFyaW5lID0gIk1hcmluZSIpCgojIGdyb3VwIE1hcmluZSBpbnZlcnRlYnJhdGVzL3BsYW50cyBpbiB3aXRoIEFsbAp0cmVuZHNbLCB0YXhhX21vZDIgOj0gdGF4YV9tb2RdCnRyZW5kc1t0YXhhX21vZCA9PSAnTWFyaW5lIGludmVydGVicmF0ZXMvcGxhbnRzJywgdGF4YV9tb2QyIDo9ICdBbGwnXQpgYGAKCgojIyMgTG9nLXRyYW5zZm9ybSBzb21lIHZhcmlhYmxlcywgdGhlbiBjZW50ZXIgYW5kIHNjYWxlLiAKYGBgIHtyIGNlbnRlciBhbmQgc2NhbGV9CnRyZW5kc1ssIHRlbXBhdmUuc2MgOj0gc2NhbGUodGVtcGF2ZSldCnRyZW5kc1ssIHRlbXBhdmVfbWV0YWIuc2MgOj0gc2NhbGUodGVtcGF2ZV9tZXRhYildCnRyZW5kc1ssIHNlYXMuc2MgOj0gc2NhbGUoc2VhcyldCnRyZW5kc1ssIG1pY3JvY2xpbS5zYyA6PSBzY2FsZShsb2cobWljcm9jbGltKSldCnRyZW5kc1ssIHRlbXB0cmVuZC5zYyA6PSBzY2FsZSh0ZW1wdHJlbmQsIGNlbnRlciA9IEZBTFNFKV0KdHJlbmRzWywgdGVtcHRyZW5kX2Ficy5zYyA6PSBzY2FsZShhYnModGVtcHRyZW5kKSwgY2VudGVyID0gRkFMU0UpXSAjIGRvIG5vdCBjZW50ZXIsIHNvIHRoYXQgMCBpcyBzdGlsbCAwIHRlbXBlcmF0dXJlIGNoYW5nZQp0cmVuZHNbLCBtYXNzLnNjIDo9IHNjYWxlKGxvZyhtYXNzX21lYW5fd2VpZ2h0KSldCnRyZW5kc1ssIHNwZWVkLnNjIDo9IHNjYWxlKGxvZyhzcGVlZF9tZWFuX3dlaWdodCsxKSldCnRyZW5kc1ssIGxpZmVzcGFuLnNjIDo9IHNjYWxlKGxvZyhsaWZlc3Bhbl9tZWFuX3dlaWdodCkpXQp0cmVuZHNbLCBjb25zdW1lcmZyYWMuc2MgOj0gc2NhbGUoY29uc2ZyYWMpXQp0cmVuZHNbLCBlbmRvdGhlcm1mcmFjLnNjIDo9IHNjYWxlKGVuZG9mcmFjKV0KdHJlbmRzWywgbnNwcC5zYyA6PSBzY2FsZShsb2coTnNwcCkpXQp0cmVuZHNbLCB0aGVybWFsX2JpYXMuc2MgOj0gc2NhbGUodGhlcm1hbF9iaWFzKV0KdHJlbmRzWywgbnBwLnNjIDo9IHNjYWxlKGxvZyhucHApKV0KdHJlbmRzWywgdmVnLnNjIDo9IHNjYWxlKGxvZyh2ZWcrMSkpXQp0cmVuZHNbLCBodW1hbl9ib3dsZXIuc2MgOj0gc2NhbGUobG9nKGh1bWFuX2Jvd2xlcisxKSksIGJ5ID0gUkVBTE0yXSAjIHNlcGFyYXRlIHNjYWxpbmcgYnkgcmVhbG0KdHJlbmRzW1JFQUxNMiA9PSAnVGVyckZyZXNoJywgaHVtYW5fZm9vdHByaW50LnNjIDo9IHNjYWxlKGxvZyhodW1hbl92ZW50ZXIrMSkpXQp0cmVuZHNbUkVBTE0yID09ICdNYXJpbmUnLCBodW1hbl9mb290cHJpbnQuc2MgOj0gc2NhbGUobG9nKGh1bWFuX2hhbHBlcm4pKV0KYGBgCgoKIyMjIERvIHRoZSB2YXJpYWJsZXMgbG9vayBvaz8KIyMjIyBVbnNjYWxlZApgYGB7ciBoaXN0b2dyYW1zIHVuc2NhbGVkLCBmaWcuaGVpZ2h0ID0gOX0KIyBoaXN0b2dyYW1zIHRvIGV4YW1pbmUKY2V4bWFpbiA9IDAuNgpwYXIobWZyb3cgPSBjKDUsNCkpCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KG1pbnlyQlQsIG1haW4gPSAnU3RhcnQgeWVhcicsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChtYXh5ckJUIC0gbWlueXJCVCwgbWFpbiA9ICdEdXJhdGlvbiAoeWVhcnMpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KG55ckJULCBtYWluID0gJ051bWJlciBvZiBzYW1wbGVkIHllYXJzJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KG1hc3NfbWVhbl93ZWlnaHQsIG1haW4gPSAnTWFzcyAoZyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3Qoc3BlZWRfbWVhbl93ZWlnaHQsIG1haW4gPSAnU3BlZWQgKGttL2hyKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChsaWZlc3Bhbl9tZWFuX3dlaWdodCwgbWFpbiA9ICdMaWZlc3BhbiAoeXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHRlbXBhdmVfbWV0YWIsIG1haW4gPSAnTWV0YWJvbGljIHRlbXBlcmF0dXJlICjCsEMpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGNvbnNmcmFjLCBtYWluID0gJ0NvbnN1bWVycyAoZnJhY3Rpb24pJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGVuZG9mcmFjLCBtYWluID0gJ0VuZG90aGVybXMgKGZyYWN0aW9uKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdCh0ZW1wYXZlLCBtYWluID0gJ0Vudmlyb25tZW50YWwgdGVtcGVyYXR1cmUgKMKwQyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QodGVtcHRyZW5kLCBtYWluID0gJ1RlbXBlcmF0dXJlIHRyZW5kICjCsEMveXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHNlYXMsIG1haW4gPSAnU2Vhc29uYWxpdHkgKMKwQyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QobWljcm9jbGltLCBtYWluID0gJ01pY3JvY2xpbWF0ZXMgKMKwQyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QoTnNwcCwgbWFpbiA9ICdTcGVjaWVzIHJpY2huZXNzJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHRoZXJtYWxfYmlhcywgbWFpbiA9ICdUaGVybWFsIGJpYXMgKMKwQyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QobnBwLCBtYWluID0gJ05ldCBwcmltYXJ5IHByb2R1Y3Rpdml0eScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdCh2ZWcsIG1haW4gPSAnVmVnZXRhdGlvbiBpbmRleCcsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChodW1hbl9ib3dsZXIsIG1haW4gPSAnSHVtYW4gaW1wYWN0IHNjb3JlIChCb3dsZXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGh1bWFuX3ZlbnRlciwgbWFpbiA9ICdIdW1hbiBpbXBhY3Qgc2NvcmUgKFZlbnRlciknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QoaHVtYW5faGFscGVybiwgbWFpbiA9ICdIdW1hbiBpbXBhY3Qgc2NvcmUgKEhhbHBlcm4pJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCgpgYGAKCiMjIyMgU2NhbGVkCmBgYHtyIGhpc3RvZ3JhbXMgc2NhbGVkLCBmaWcuaGVpZ2h0ID0gOX0KIyBoaXN0b2dyYW1zIHRvIGV4YW1pbmUKY2V4bWFpbiA9IDAuNgpwYXIobWZyb3cgPSBjKDUsNCkpCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHRlbXBhdmUuc2MsIG1haW4gPSAnRW52aXJvbm1lbnRhbCB0ZW1wZXJhdHVyZSAowrBDKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdCh0ZW1wYXZlX21ldGFiLnNjLCBtYWluID0gJ01ldGFib2xpYyB0ZW1wZXJhdHVyZSAowrBDKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChzZWFzLnNjLCBtYWluID0gJ1NlYXNvbmFsaXR5ICjCsEMpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KG1pY3JvY2xpbS5zYywgbWFpbiA9ICdsb2cgTWljcm9jbGltYXRlcyAowrBDKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdCh0ZW1wdHJlbmQuc2MsIG1haW4gPSAnVGVtcGVyYXR1cmUgdHJlbmQgKMKwQy95ciknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QodGVtcHRyZW5kX2Ficy5zYywgbWFpbiA9ICdhYnMoVGVtcGVyYXR1cmUgdHJlbmQpICjCsEMveXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KG1hc3Muc2MsIG1haW4gPSAnbG9nIE1hc3MgKGcpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHNwZWVkLnNjLCBtYWluID0gJ2xvZyBTcGVlZCAoa20vaHIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGxpZmVzcGFuLnNjLCBtYWluID0gJ2xvZyBMaWZlc3BhbiAoeXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGNvbnN1bWVyZnJhYy5zYywgbWFpbiA9ICdDb25zdW1lcnMgKGZyYWN0aW9uKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChlbmRvdGhlcm1mcmFjLnNjLCBtYWluID0gJ0VuZG90aGVybXMgKGZyYWN0aW9uKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChuc3BwLnNjLCBtYWluID0gJ2xvZyBTcGVjaWVzIHJpY2huZXNzJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHRoZXJtYWxfYmlhcy5zYywgbWFpbiA9ICdUaGVybWFsIGJpYXMgKMKwQyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QobnBwLnNjLCBtYWluID0gJ2xvZyBOZXQgcHJpbWFyeSBwcm9kdWN0aXZpdHknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QodmVnLnNjLCBtYWluID0gJ2xvZyBWZWdldGF0aW9uIGluZGV4JywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGh1bWFuX2Jvd2xlci5zYywgbWFpbiA9ICdsb2cgSHVtYW4gaW1wYWN0IHNjb3JlIChCb3dsZXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGh1bWFuX2Zvb3RwcmludC5zYywgbWFpbiA9ICdsb2cgSHVtYW4gaW1wYWN0IHNjb3JlIChWZW50ZXIgJiBIYWxwZXJuKScsIGNleC5tYWluID0gY2V4bWFpbildKQoKYGBgCgoKCiMjIyBDaGVjayBjb3JyZWxhdGlvbnMgYW1vbmcgdmFyaWFibGVzLiBQZWFyc29uJ3MgciBpcyBvbiB0aGUgbG93ZXIgZGlhZ29uYWwuCmBgYHtyIHBhaXJzLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTB9CnBhbmVsLmNvciA8LSBmdW5jdGlvbih4LCB5LCBkaWdpdHMgPSAyLCBwcmVmaXggPSAiIiwgY2V4LmNvciwgLi4uKQp7CiAgICB1c3IgPC0gcGFyKCJ1c3IiKTsgb24uZXhpdChwYXIodXNyKSkKICAgIHBhcih1c3IgPSBjKDAsIDEsIDAsIDEpKQogICAgciA8LSBjb3IoeCwgeSwgdXNlID0gJ3BhaXJ3aXNlLmNvbXBsZXRlLm9icycpCiAgICB0eHQgPC0gZm9ybWF0KGMociwgMC4xMjM0NTY3ODkpLCBkaWdpdHMgPSBkaWdpdHMpWzFdCiAgICB0eHQgPC0gcGFzdGUwKHByZWZpeCwgdHh0KQogICAgaWYobWlzc2luZyhjZXguY29yKSkgY2V4LmNvciA8LSAwLjgvc3Ryd2lkdGgodHh0KQogICAgdGV4dCgwLjUsIDAuNSwgdHh0KSAjLCBjZXggPSBjZXguY29yICogcikKfQpwYWlycyhmb3JtdWxhID0gfiB0ZW1wYXZlLnNjICsgdGVtcGF2ZV9tZXRhYi5zYyArIHNlYXMuc2MgKyBtaWNyb2NsaW0uc2MgKyB0ZW1wdHJlbmQuc2MgKyB0ZW1wdHJlbmRfYWJzLnNjICsgbWFzcy5zYyArIHNwZWVkLnNjICsgbGlmZXNwYW4uc2MgKyBjb25zdW1lcmZyYWMuc2MgKyBlbmRvdGhlcm1mcmFjLnNjICsgbnNwcC5zYyArIHRoZXJtYWxfYmlhcy5zYyArIG5wcC5zYyArIHZlZy5zYyArIGh1bWFuX2Jvd2xlci5zYyArIGh1bWFuX2Zvb3RwcmludC5zYywgZGF0YSA9IHRyZW5kcywgZ2FwID0gMS8xMCwgY2V4ID0gMC4yLCBjb2wgPSAnIzAwMDAwMDIyJywgbG93ZXIucGFuZWwgPSBwYW5lbC5jb3IpCgpgYGAKCk1hc3MgYW5kIGxpZmVzcGFuIGxvb2sgdGlnaHRseSBjb3JyZWxhdGVkLCBidXQgciBvbmx5IDAuNTYuLi4/ClRlbXBhdmVfbWV0YWIgYW5kIGxpZmVzcGFuIGRvbid0IGxvb2sgdGlnaHRseSBjb3JyZWxhdGVkLCBidXQgcj0gLTAuODEgClRlbXBhdmVfbWV0YWIgYW5kIHNwZWVkIGRvbid0IGxvb2sgdGlnaHRseSBjb3JyZWxhdGVkLCBidXQgcj0gLTAuODMgCkxpZmVzcGFuIGFuZCBzcGVlZCBkb24ndCBsb29rIHRpZ2h0bHkgY29ycmVsYXRlZCwgYnV0IHIgPSAwLjczCg==